package io.gitee.caoxiaoyu97.service.split.Interceptor;

import io.gitee.caoxiaoyu97.service.split.api.ServiceSplit;
import io.gitee.caoxiaoyu97.service.split.api.ServiceSplitImplTemplate;
import io.gitee.caoxiaoyu97.service.split.util.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.AopUtils;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/*********************************************************
 * 文件名称：CxycloudServiceSplitWrapperInterceptor.java
 * 系统名称：cxycloud
 * 模块名称：io.gitee.caoxiaoyu97.service.split
 * 功能说明：服务分离后的代理类
 * 开发人员 @author：caoxy
 * 开发时间 @date：2023/8/4 15:55
 * 修改记录：程序版本  修改日期  修改人员  修改单号  修改说明
 *********************************************************/
@Slf4j
public class CxycloudServiceSplitWrapperInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        long startTime = System.currentTimeMillis();
        Method method = invocation.getMethod();
        Class<?> declaringClass = method.getDeclaringClass();
        try {

            if (AopUtils.isToStringMethod(method)) {
                StringBuffer buf = new StringBuffer("proxy for service");
                if (invocation.getThis() != null) {
                    buf.append("[").append(invocation.getThis().toString()).append("]");
                }

                return buf.toString();
            }
            Object[] args = invocation.getArguments();
            ServiceSplitImplTemplate bean = checkAndGetImpl(method, args);
            return bean.impl(args[0]);
        }finally {
            long endTime = System.currentTimeMillis();
            log.info("内部{}.{}服务，交易处理总耗时[{}]ms", new Object[]{declaringClass.getName(), method.getName(), endTime - startTime});;
        }

    }

    private static ServiceSplitImplTemplate checkAndGetImpl(Method method, Object[] args) {
        if (args.length != 1){
            throw new RuntimeException(method.getName() + "参数必须是一个");
        }
        Object arg = args[0];
        ServiceSplit annotation = method.getAnnotation(ServiceSplit.class);
        if (annotation == null){
            throw new RuntimeException(method.getName() + "未配置转换注释ServiceSplit.class");
        }

        Class<? extends ServiceSplitImplTemplate> implClass = annotation.value();
        Class<?> reqClass = null;
        Class<?> respClass = null;
        Type[] genericInterfaces = implClass.getGenericInterfaces();
        for (Type genericInterface : genericInterfaces) {
            if (genericInterface instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
                if (parameterizedType.getRawType() == ServiceSplitImplTemplate.class) {
                    Type[] typeArguments = parameterizedType.getActualTypeArguments();
                    reqClass = (Class<?>) typeArguments[0];
                    respClass = (Class<?>) typeArguments[1];
                }
            }
        }
        if (arg.getClass() != reqClass){
            throw new RuntimeException(method.getName() + "入参与指定的实现类入参不一致");
        }
        if(method.getReturnType() != respClass){
            throw new RuntimeException(method.getName() + "出参与指定的实现类出参不一致");
        }
        ServiceSplitImplTemplate bean = SpringUtils.getBean(implClass);
        return bean;
    }
}
